/*********************************************************************************
 *      Copyright:  (C) 2024 huangzhuo
 *                  All rights reserved.
 *
 *       Filename:  main.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(2024年04月22日)
 *         Author:  huangzhuo <1785067760@qq.com>
 *      ChangeLog:  1, Release initial version on "2024年04月22日 19时20分16秒"
 *                 
 ********************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <getopt.h>
#include <libgen.h>
#include <string.h>
#include <errno.h>

#include "pack.h"
#include "logger.h" 
#include "get_data.h"
#include "proc.h"
#include "socket.h"
#include "database.h"

#define DAEMON_PIDFILE             "/tmp/.socketd.pid"

void print_usage(char *progname);

int main(int argc, char **argv)
{
	int				device_len	=	20;
	pack_data_t		data;
	char			msg[512];
	time_t			last_time 	= 	0;
	time_t			now			=	0;
	const	char	*db_name	=	"socket.db";
	const	char	*table_name	=	"staging";
	sqlite3 		*db;	
	float			temp		=	0;
	int				rv 			= 	1;
	int				ch 			= 	1;
	int				interval 	= 	2;
	socket_t		sock;
	int				daemon_run	=	1;
	char			*serverip 	= 	NULL;
	int				port 		= 	0;
	int				sample_flag = 	0;
	int             bytes 	= 	0;
	char           	*logfile	=	"client.log";
    int           	loglevel	=	LOG_LEVEL_INFO;
    int       		logsize		=	10; /* logfile size max to 10K */
	 struct option 	opts[] =
    {
        {"ipaddr", required_argument, NULL, 'i'},
        {"port", required_argument, NULL, 'p'},
        {"time", required_argument, NULL, 't'},
		{"console",no_argument,NULL,'c'},
        {"debug", no_argument, NULL, 'd'},
        {"help", no_argument, NULL, 'h'},
        {NULL, 0, NULL, 0}
    };

    while ((ch = getopt_long(argc, argv, "i:p:t:cdh", opts, NULL)) != -1)
    {
        switch (ch)
        {
            case 'i':
				serverip = optarg;
                break;
            case 'p':
                port = atoi(optarg);
                break;
            case 't':
            	interval = atoi(optarg);
                break;
            case 'c': 
                logfile="console";
                loglevel=LOG_LEVEL_DEBUG;
                break;
			case 'd':
				daemon_run=0;
				break;
            case 'h':
                print_usage(argv[0]);
                return 0;
        }
    }
    
    if( !serverip || !port )
    {
        print_usage(argv[0]);
        return 0;
    }

	if(log_open(logfile, loglevel, logsize, THREAD_LOCK_NONE) < 0 )
	{
		printf("Failed to initialize log\n");
		return -1;
	} 
    
	db = init_data(db_name, table_name);
	if(!db)
	{
		log_warn("Failed to initialize database.\n");
		return -2;
	}

	if( socket_init(&sock, serverip, port) < 0)
    {
        log_warn("Failed to initialize socket\n");
        return -3;
    }
	if(!daemon_run)
	{
		install_default_signal();

		daemon(1,1);
	}
    printf("program start running.\n");
	
	time(&last_time);
	while( !g_signal.stop )
	{
		/*sample_flag = 0则不采样; = 1则采样*/
		sample_flag = 0;

		time(&now);
		if(difftime(now,last_time)>=interval)
		{
			last_time=now;
			sleep(1);
		
			if((rv=get_temperature(&data.temperature))<0)
			{
				log_warn("get temp error\n");
			}
			if(rv=(get_device_name(data.id, device_len, DEVICE_NUMBER))<0)
			{
				log_warn("get id error\n");
			}
			if(rv=(get_current_time(data.time))<0)
			{
				log_warn("get time error\n");
			}
			bytes=snprintf(msg, sizeof(msg), "%s|%s|%f",data.id,data.time,data.temperature/1000);
			//printf("msg:%s\n",msg);
			/*采样成功*/
			sample_flag = 1;
		}
		if(sock.fd < 0)
		{
			socket_connect(&sock);
		}
		if(socket_alive(sock.fd) < 0)
		{
			if(sock.fd > 0)
			{
				log_info("socket connect error, try to reconnectting...\n");
				socket_close(&sock);/*sock.fd == -1*/
			}
		}
		if(sock.fd < 0)
		{
			if(sample_flag)
			{
				insert_data(db, &data);
				socket_close(&sock);
			}
			continue;
		}
		if(sample_flag)
		{
			if(socket_senddata(&sock, msg, bytes) < 0)
			{
				log_warn("send data error, save in staging\n");
				insert_data(db, &data);
				socket_close(&sock);
			}
		}
		if( 0==pop_data(db, &data))
		{
			bytes=snprintf(msg, sizeof(msg), "%s|%s|%f", data.id,data.time,data.temperature/1000);
			if(socket_senddata(&sock, msg, bytes) < 0)
			{
				log_warn("send data error\n");
				socket_close(&sock);
			}
			else
			{
				log_info("send data successfully, delete staging's data:%s\n",msg);
				delete_data(db, &data);
			}
		}
		msleep(100);
	}
cleanup:
    socket_close(&sock);
    close_table(db);
    unlink(DAEMON_PIDFILE);
    log_close();

    return 0;
}

void print_usage(char *progname)
{
    printf("%s usage: \n",progname);
    printf("-i(--ipaddr): specify server IP address\n");
    printf("-p(--port): specify server port.\n");
    printf("-t(--time): Upload interval\n");
	printf("-c: log_xx -> prinf to console\n");
	printf("-d(daemon):daemon(1,1)\n");
    printf("-h(--Help): print this help information.\n");
    return ;
}

